home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / misc / btngo.zip / BTNGOC.ZIP / ITEMDATA.CPP < prev    next >
C/C++ Source or Header  |  1993-09-28  |  19KB  |  519 lines

  1. #include<windows.h>
  2. #include<ctype.h>
  3. #include"wstring.hpp"
  4. #include"itemdata.hpp"
  5.  
  6. #ifdef DEBUG_SCREENS
  7. extern WinMessageString screen;
  8. #endif
  9. extern WinMessageString errscreen;
  10. extern unsigned int winver;
  11.  
  12. /////////////////////////////////////
  13. // defines
  14. #define CFP(x) (&((char __far *)memptr)[x]) // create char __far * x bytes into buffer
  15. #define CFP2(x) (&((char __far *)memptr2)[x]) // create char __far * x bytes into buffer
  16.  
  17. /////////////////////////////////////
  18. // local data types
  19.  
  20. struct GroupInfo{
  21.     WORD name;
  22.     WORD executable;
  23.     WORD executable_with_path;
  24.     WORD parameters;
  25.     WORD default_directory;
  26.     WORD minimized;
  27. };
  28. struct GroupFileHeader{
  29.     char cIdentifier[4];
  30.     WORD wCheckSum;
  31.     WORD cbGroup;
  32.     WORD nCmdShow;
  33.     RECT rcNormal;
  34.     POINT ptMin;
  35.     WORD pName;
  36.     WORD wLogPixelsX;
  37.     WORD wLogPixelsY;
  38.     BYTE bBitsPerPixel;
  39.     BYTE bPlanes;
  40.     WORD wReserved;
  41.     WORD cItems;
  42. };
  43. struct ItemData{
  44.     POINT pt;
  45.     WORD iIcon; // 0 if normal, 1 if minimized
  46.     WORD cbResource;
  47.     WORD cbANDPlane;
  48.     WORD cbXORPlane;
  49.     WORD pHeader;
  50.     WORD pANDPlane;
  51.     WORD pXORPlane;
  52.     WORD pName;
  53.     WORD pCommand;
  54.     WORD pIconPath; // 0 or ptr to initial path
  55. };
  56. struct TagData{
  57.     WORD wID;
  58.     WORD wItem;
  59.     WORD cb;
  60.     union{
  61.         char cnext[1];
  62.         int inext;
  63.     }next;
  64. };
  65. struct IconHeader{ // pointed to by ItemData.pHeader
  66.     int xHotSpot;
  67.     int yHotSpot;
  68.     int cx; // icon width
  69.     int cy; // icon height
  70.     int cbWidth; // bytes per row including WORD alignment
  71.     BYTE bPlanes; // nbr planes
  72.     BYTE bBitsPixel; // bits per pixel
  73. };
  74. /////////////////////////////////////
  75. // GroupFile member functions
  76.  
  77. GroupFile::GroupFile(char *p){
  78.     opened=0;
  79.     items_to_read=0;
  80.     tag_bytes=0;
  81.     memhandle=NULL;
  82.     memptr=NULL;
  83.     memhandle2=NULL;
  84.     memptr2=NULL;
  85.     got_icon_default_data=0;
  86.     set_filename(p);
  87. }
  88. GroupFile::~GroupFile(){
  89.     if(opened)_lclose(hf);
  90.     if(memhandle!=NULL){
  91.         if(memptr!=NULL)GlobalUnlock(memhandle);
  92.         GlobalFree(memhandle);
  93.     }
  94.     if(memhandle2!=NULL){
  95.         if(memptr2!=NULL)GlobalUnlock(memhandle2);
  96.         GlobalFree(memhandle2);
  97.     }
  98.     #ifdef DEBUG_SCREENS
  99.     screen<<grpfil<<" destructed\n";
  100.     screen.show();
  101.     #endif
  102. }
  103. void GroupFile::set_filename(char *p){
  104.     error_condition_exists=(NULL==(grpfil=p))?1:0;
  105. }
  106. int GroupFile::openfile(){
  107.     if(error())return 0;
  108.     // assume failure so can just return
  109.     error_condition_exists=1;
  110.     if(opened)return 0;
  111.     opened=((hf=_lopen(grpfil,READ))==HFILE_ERROR)?0:1;
  112.     if(!opened)return 0;
  113.     filebytes=_llseek(hf,0,2); // go to end of file
  114.     if(filebytes==HFILE_ERROR||_llseek(hf,0,0)==HFILE_ERROR)return 0; // go to beginning
  115.     if(filebytes>60000L){
  116.         errscreen<<"Group file is too large. Aborting.\n";
  117.         return 0;
  118.     }
  119.     if(filebytes<(sizeof(GroupFileHeader)+2+sizeof(ItemData)+sizeof(IconHeader))){
  120.         errscreen<<"Group file is empty or too small. Aborting.\n";
  121.         return 0;
  122.     }
  123.     if(NULL==(memhandle=GlobalAlloc(GMEM_FIXED,filebytes))){
  124.         errscreen<<"Could not allocate memory\n";
  125.         return 0;
  126.     }
  127.     if(NULL==(memptr=GlobalLock(memhandle))){
  128.         errscreen<<"Could not lock memory\n";
  129.         return 0;
  130.     }
  131.     if(_lread(hf,memptr,(UINT)filebytes)!=(UINT)filebytes){
  132.         errscreen<<"Could not read group file. Aborting.\n";
  133.         return 0;
  134.     }
  135.     GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
  136.     if(p->cIdentifier[0]!='P'||p->cIdentifier[1]!='M'||
  137.     p->cIdentifier[2]!='C'||p->cIdentifier[3]!='C'){
  138.         errscreen<<"Group file corrupted. Aborting.\n";
  139.         return 0;
  140.     }
  141.     pItemOffset=(int __far *)&p[1];
  142.     {
  143.         int ok=0;
  144.         for(;;){
  145.             WORD x;
  146.             if(p->cItems<1)break;
  147.             for(x=0;x<p->cItems;x++){
  148.                 if(pItemOffset[x]!=0){
  149.                     ok=1;
  150.                     break;
  151.                 }
  152.             }
  153.             break;
  154.         }
  155.         if(!ok){
  156.             errscreen<<"Group file is empty. Aborting.";
  157.             return 0;
  158.         }
  159.     }
  160.     _lclose(hf);
  161.     opened=0;
  162.     error_condition_exists=0;
  163.     return 1;
  164. }
  165. void GroupFile::readheader(){
  166.     if(error())return;
  167.     GroupFileHeader _far *p=(GroupFileHeader __far *)memptr;
  168.     // pItemOffset=(int *)&((GroupFileHeader *)memptr)[1];
  169.     items_to_read=p->cItems;
  170.     #ifdef DEBUG_SCREENS
  171.     screen<<"Group name is "<<CFP(p->pName)<<"\n";
  172.     #endif
  173.     // now, if in Win 3.1, associate tag data with items
  174.     // this is because the wItem part of TagData will become
  175.     // invalid (we'll need to sort the icons by position)
  176.     // so we'll use this convention:
  177.     //    ItemData  == TagData wID   usage
  178.     //    --------     -----------  -----------------------------
  179.     //     iIcon        0x8103       0 if normal, 1 if minimized
  180.     //     pIconPath    0x8101       0 or ptr to initial path
  181.     //
  182.     // pseudocode:
  183.     //      set all iIcons to 0, pIconPaths to 0
  184.     //      if in Windows 3.1 TagData may be present so
  185.     //          for each TagData entry
  186.     //              apply data to ItemData entry
  187.     //          end for
  188.     //      end if
  189.     {
  190.         int t;
  191.         ItemData __far *p;
  192.         for(t=0;t<items_to_read;t++){
  193.             if(pItemOffset[t]==0)continue;
  194.             p=(ItemData __far *)CFP(pItemOffset[t]);
  195.             p->iIcon=0;
  196.             p->pIconPath=0;
  197.         }
  198.     }
  199.     if(winver>=0x30A){
  200.         int keep_going=0;
  201.         GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
  202.         ItemData __far *q;
  203.         TagData __far *tdp;
  204.         if(filebytes>=(LONG)(p->cbGroup+6)){ // '6' sted sizeof(TagData) - sizeof(union)
  205.             tdp=(TagData __far *)CFP(p->cbGroup);
  206.             keep_going=1;
  207.         }
  208.         while(keep_going){
  209.             switch(tdp->wID){
  210.             case 0xFFFF: keep_going=0; break;
  211.             case 0x8101: // path in next.cnext
  212.                 q=(ItemData __far *)CFP(pItemOffset[tdp->wItem]);
  213.                 q->pIconPath=(WORD)(tdp->next.cnext-(char __far *)memptr);
  214.                 break;
  215.             case 0x8103: // app should be minimized
  216.                 q=(ItemData __far *)CFP(pItemOffset[tdp->wItem]);
  217.                 q->iIcon=1;
  218.                 break;
  219.             }
  220.             // '6' in next line is sizeof(TagData) - sizeof(union)
  221.             if((LONG)(((char __far *)tdp-(char __far *)memptr)+tdp->cb+6)>filebytes){
  222.                 keep_going=0;
  223.                 continue;
  224.             }
  225.             tdp=(TagData __far *)(((char __far *)tdp)+tdp->cb);
  226.         }
  227.     }
  228.     // ok now we can sort the item data by the icon's position
  229.     // so the group looks like it ought to
  230.     // use old'n'lame selection sort but it's good enough here...
  231.     if(items_to_read>1){
  232.         int min,x,left=items_to_read;
  233.         unsigned int temp;
  234.         unsigned int __far *p=(unsigned int __far *)pItemOffset;
  235.         while(left-->1){
  236.             for(x=0,min=0;x<=left;x++)if(second_lower(p[min],p[x]))min=x;
  237.             if(min!=0){temp=p[min];p[min]=*p;*p=temp;}
  238.             p++;
  239.         }
  240.     }
  241.     // now create the compacted version of the file
  242.     // first accumulate target size, then allocate space, then copy space
  243.     unsigned long size=0;
  244.     {
  245.         int left=items_to_read,found_items=0;
  246.         unsigned int __far *p=(unsigned int __far *)pItemOffset;
  247.         ItemData __far *i;
  248.         while(left&&*p){
  249.             i=(ItemData __far *)CFP(*p);
  250.             size+=sizeof(GroupInfo); // space for array entry
  251.             if(i->pName)size+=1+lstrlen(CFP(i->pName)); // space for entry's displayed name
  252.             if(i->pCommand)size+=1+lstrlen(CFP(i->pCommand)); // space for command line
  253.             if(i->pIconPath)size+=1+lstrlen(CFP(i->pIconPath)); // space for command path
  254.             p++;
  255.             left--;
  256.             found_items++;
  257.         }
  258.         items_to_read=found_items; // 'forget' about NULL entries
  259.     }
  260.     // now we know how much memory to get
  261.     // let's get it
  262.     if(size>0)for(;;){
  263.         if(NULL==(memhandle2=GlobalAlloc(GMEM_FIXED,size))){
  264.             errscreen<<"Could not allocate memory for program data\n";
  265.             break;
  266.         }
  267.         if(NULL==(memptr2=GlobalLock(memhandle2))){
  268.             errscreen<<"Could not lock memory for program data\n";
  269.             break;
  270.         }
  271.         // now wind through group file
  272.         // pseudocode:    while(items to process)
  273.         //                    copy data into *gi
  274.         //                    build and copy strings, put offsets into *gi
  275.         //                    increment ItemData pointer
  276.         //                    increment GroupInfo pointer
  277.         GroupInfo __far *gi=(GroupInfo __far *)memptr2;
  278.         char __far *space=(char __far *)&gi[items_to_read]; // point to string space
  279.         int x=items_to_read;
  280.         unsigned int __far *p=(unsigned int __far *)pItemOffset;
  281.         ItemData __far *id;
  282.         char nb1[250],nb2[250];
  283.         while(x--){
  284.             id=(ItemData __far *)CFP(*p);
  285.             gi->minimized=id->iIcon;                    // GroupInfo.minimized
  286.             gi->name=(WORD)(space-(char __far *)memptr2); // GroupInfo.name
  287.             lstrcpy(space,CFP(id->pName));
  288.             while(*space++); // point past null terminator
  289.             if(id->pCommand!=0)lstrcpy(nb1,CFP(id->pCommand)); // defdir\\exename parms
  290.             else nb1[0]=0;
  291.             if(id->pIconPath!=0)lstrcpy(nb2,CFP(id->pIconPath)); // exepath
  292.             else nb2[0]=0;
  293.             gi->executable_with_path=(WORD)(space-(char __far *)memptr2); // GroupInfo.executable_with_path
  294.             lstrcpy(space,nb2);
  295.             while(*space)space++; // point at null terminator; we'll append .EXE name
  296.             // now find .EXE name
  297.             // first scan off whitespace
  298.             char *nb1_begin=nb1;
  299.             while(isspace(*nb1_begin))nb1_begin++;
  300.             // now go to end of first arg
  301.             char *parms=nb1_begin;
  302.             while(*parms){
  303.                 if(isspace(*parms))break;
  304.                 parms++;
  305.             }
  306.             // parms points at whitespace between first arg and parameters
  307.             // kill the whitespace
  308.             while(*parms){
  309.                 if(isspace(*parms)){
  310.                     *parms=0;
  311.                     parms++;
  312.                 }
  313.                 else break;
  314.             }
  315.             // now parms points at the parameters, or a null terminator
  316.             // nb1_begin points at defdir\\exename (whitespace stripped both ends)
  317.             // point exename at executable's name
  318.             char *exename=nb1_begin;
  319.             int got_defdir=0;
  320.             while(*exename)exename++; // point at null terminator
  321.             while(exename>nb1_begin){
  322.                 exename--;
  323.                 if(*exename=='\\'||*exename==':'){
  324.                     got_defdir=(int)(exename-nb1_begin);
  325.                     if(exename>nb1_begin&&exename[-1]==':')got_defdir++;
  326.                     exename++;
  327.                     break; // nb1_begin points at defdir; exename points at executable name
  328.                 }
  329.             }
  330.             gi->executable=(WORD)(space-(char __far *)memptr2); // GroupInfo.executable
  331.             lstrcpy(space,exename);
  332.             while(*space++); // point past null terminator
  333.             if(*parms==0)gi->parameters=0;                        // GroupInfo.parameters
  334.             else{
  335.                 gi->parameters=(WORD)(space-(char __far *)memptr2);
  336.                 lstrcpy(space,parms);
  337.                 while(*space++); // point past null terminator
  338.             }
  339.             if(got_defdir==0)gi->default_directory=0;            // GroupInfo.default_directory
  340.             else{
  341.                 gi->default_directory=(WORD)(space-(char __far *)memptr2);
  342.                 while(got_defdir--)*space++=*nb1_begin++;
  343.                 *space++=0; // make null terminator, go past it
  344.             }
  345.             p++;
  346.             gi++;
  347.         }
  348.         break;
  349.     }
  350. }
  351. int GroupFile::second_lower(unsigned int first,unsigned int second){
  352.     // compare function for GroupFile::readheader()
  353.     // returns 1 if second should be *before* first
  354.     if(!second)return 0; // it's null, never make it first
  355.     if(!first)return 1; // it's null so second *should* be first
  356.     // now we have two non-NULL entries. Make pointers to item data
  357.     ItemData __far *pfirst=(ItemData __far *)CFP(first);
  358.     ItemData __far *psecond=(ItemData __far *)CFP(second);
  359.     // Which has smaller Y value?
  360.     if(pfirst->pt.y > psecond->pt.y)return 1;
  361.     if(pfirst->pt.y < psecond->pt.y)return 0;
  362.     // OK, depend on X value
  363.     return (pfirst->pt.x > psecond->pt.x)?1:0;
  364. }
  365. int GroupFile::showitem(int offset){
  366. /*
  367.     pseudocode:
  368.         bail out if already failed
  369.         set error_condition_exists to indicate failure
  370.         if read itemdata fails return
  371.         if read 
  372.         set error_condition_exists to indicate success        
  373.     returns 0 for no item found, 1 for valid item found
  374. */
  375.     if(error())return 0;
  376.     if(memptr==NULL)return 0;
  377.     if(offset>=items_to_read)return 0;
  378.     if(pItemOffset[offset]==0)return 0; //NULL entry
  379.     ItemData __far *p=(ItemData __far *)CFP(pItemOffset[offset]);
  380.     error_condition_exists=1;
  381.     // set default to failure, so we can just return on error
  382.     #ifdef DEBUG_SCREENS
  383.     screen<<offset<<" "<<CFP(p->pName)<<" ("<<CFP(p->pCommand)<<")\n";
  384.     #endif
  385.     // well, we got here so all must be well
  386.     error_condition_exists=0;
  387.     return 1;
  388. }
  389. char __far *GroupFile::get_group_name(){
  390.     if(error())return NULL;
  391.     if(memptr==NULL)return NULL;
  392.     GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
  393.     if(p->pName==0)return NULL;
  394.     return CFP(p->pName);
  395. }
  396. char __far *GroupFile::get_item_name(int offset){
  397. /*
  398.     returns char * to item name if it's valid (non-null, has printables)
  399. */
  400.     if(error())return NULL;
  401.     if(memptr2==NULL)return NULL;
  402.     if(offset>=items_to_read)return NULL;
  403.     if(!((GroupInfo __far *)memptr2)[offset].name)return NULL;
  404.     return CFP2(((GroupInfo __far *)memptr2)[offset].name);
  405. }
  406. char __far *GroupFile::get_item_command(int offset){
  407. /*
  408.     returns char * to item's command if it's valid (non-null, has printables)
  409. */
  410.     if(error())return NULL;
  411.     if(memptr2==NULL)return NULL;
  412.     if(offset>=items_to_read)return NULL;
  413.     if(!((GroupInfo __far *)memptr2)[offset].executable_with_path)return NULL;
  414.     return CFP2(((GroupInfo __far *)memptr2)[offset].executable_with_path);
  415. }
  416. char __far *GroupFile::get_item_command_nopath(int offset){
  417. /*
  418.     returns char * to item's command if it's valid (non-null, has printables)
  419. */
  420.     if(error())return NULL;
  421.     if(memptr2==NULL)return NULL;
  422.     if(offset>=items_to_read)return NULL;
  423.     if(!((GroupInfo __far *)memptr2)[offset].executable)return NULL;
  424.     return CFP2(((GroupInfo __far *)memptr2)[offset].executable);
  425. }
  426. char __far *GroupFile::get_item_parameters(int offset){
  427.     if(error())return NULL;
  428.     if(memptr2==NULL)return NULL;
  429.     if(offset>=items_to_read)return NULL;
  430.     if(!((GroupInfo __far *)memptr2)[offset].parameters)return NULL;
  431.     return CFP2(((GroupInfo __far *)memptr2)[offset].parameters);
  432. }
  433. char __far *GroupFile::get_item_default_dir(int offset){
  434. /*
  435.     returns char * to item's path if it's valid (non-null, has printables)
  436. */
  437.     if(error())return NULL;
  438.     if(memptr2==NULL)return NULL;
  439.     if(offset>=items_to_read)return NULL;
  440.     if(!((GroupInfo __far *)memptr2)[offset].default_directory)return NULL;
  441.     return CFP2(((GroupInfo __far *)memptr2)[offset].default_directory);
  442. }
  443. int GroupFile::is_item_iconized(int offset){
  444. /*
  445.     returns 1 if item is to be run minimized, 0 if not
  446. */
  447.     if(error())return 0;
  448.     if(offset>=items_to_read)return NULL;
  449.     if(memptr2!=NULL)return (int)((GroupInfo __far *)memptr2)[offset].minimized;
  450.     if(memptr==NULL)return 0;
  451.     if(pItemOffset[offset]==0)return 0; //NULL entry
  452.     ItemData __far *p=(ItemData __far *)CFP(pItemOffset[offset]);
  453.     return (p->iIcon==0)?0:1;
  454. }
  455. HBITMAP GroupFile::get_fill_item_and_bitmap(int offset,int&x,int&y){
  456.     // caller's responsibility to delete bitmap!
  457.     if(error())return NULL;
  458.     if(memptr==NULL)return NULL;
  459.     if(offset>=items_to_read)return NULL;
  460.     if(pItemOffset[offset]==0)return NULL; //NULL entry
  461.     ItemData __far *pID=(ItemData __far *)CFP(pItemOffset[offset]);
  462.     IconHeader __far *pIH=(IconHeader __far *)CFP(pID->pHeader);
  463.     x=pIH->cx;
  464.     y=pIH->cy;
  465.     return CreateBitmap(pIH->cx,pIH->cy,1,1,(const void FAR*)CFP(pID->pANDPlane));
  466. }
  467. HBITMAP GroupFile::get_fill_item_xor_bitmap(int offset,int&x,int&y){
  468.     // caller's responsibility to delete bitmap!
  469.     if(error())return NULL;
  470.     if(memptr==NULL)return NULL;
  471.     if(offset>=items_to_read)return NULL;
  472.     if(pItemOffset[offset]==0)return NULL; //NULL entry
  473.     ItemData __far *pID=(ItemData __far *)CFP(pItemOffset[offset]);
  474.     IconHeader __far *pIH=(IconHeader __far *)CFP(pID->pHeader);
  475.     x=pIH->cx;
  476.     y=pIH->cy;
  477.     return CreateBitmap(pIH->cx,pIH->cy,pIH->bPlanes,pIH->bBitsPixel,(const void FAR*)CFP(pID->pXORPlane));
  478. }
  479. int GroupFile::get_icon_dimensions(int& height,int& width){
  480.     if(!got_icon_default_data)get_icon_default_data();
  481.     if(!got_icon_default_data){
  482.         height=0x20;
  483.         width=0x20;
  484.         return 1;
  485.     }
  486.     height=y_pixels;
  487.     width=x_pixels;
  488.     return 1;
  489. }
  490. UINT GroupFile::get_icon_planes(){
  491.     if(!got_icon_default_data)get_icon_default_data();
  492.     if(!got_icon_default_data)return 4;
  493.     return icon_planes;
  494. }
  495. UINT GroupFile::get_icon_pixelbits(){
  496.     if(!got_icon_default_data)get_icon_default_data();
  497.     if(!got_icon_default_data)return 4;
  498.     return icon_pixelbits;
  499. }
  500. void GroupFile::done_with_bitmaps(){
  501.     if(memhandle!=NULL){
  502.         if(memptr!=NULL)GlobalUnlock(memhandle);
  503.         GlobalFree(memhandle);
  504.     }
  505.     memhandle=NULL;
  506.     memptr=NULL;
  507. }
  508. void GroupFile::get_icon_default_data(){
  509.     HDC ic=CreateIC("DISPLAY",NULL,NULL,NULL);
  510.     if(ic!=NULL){
  511.         x_pixels=GetSystemMetrics(SM_CXICON);
  512.         y_pixels=GetSystemMetrics(SM_CYICON);
  513.         icon_planes=GetDeviceCaps(ic,PLANES);
  514.         icon_pixelbits=GetDeviceCaps(ic,BITSPIXEL);
  515.         got_icon_default_data=1;
  516.         DeleteDC(ic);
  517.     }
  518. }
  519.